package com.ygqh.baby.service.task.impl;

import com.ygqh.baby.ao.*;
import com.ygqh.baby.constant.Constant;
import com.ygqh.baby.exception.YgException;
import com.ygqh.baby.handler.PreBalanceHandler;
import com.ygqh.baby.model.BalanceDetailForTask;
import com.ygqh.baby.model.SchJob;
import com.ygqh.baby.po.*;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.task.YgBalanceTaskService;
import com.ygqh.baby.utils.DateConvertUtils;
import com.ygqh.baby.utils.ExceptionUtil;
import com.ygqh.baby.utils.MailUtil;
import com.ygqh.baby.utils.YgStringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @author admin
 */
@Service
public class YgBalanceTaskServiceImpl implements YgBalanceTaskService {
    protected final Logger logger = Logger.getLogger(this.getClass());
    @Autowired
    private YgUserBalanceService ygUserBalanceService;
    @Autowired
    private YgUserBalanceDetailService ygUserBalanceDetailService;
    @Autowired
    private YgTaskTimeService ygTaskTimeService;
    @Autowired
    private YgOrderService ygOrderService;
    @Autowired
    private YgReturnOrderService ygReturnOrderService;
    @Autowired
    private YgUserService ygUserService;
    @Autowired
    private YgUserCultivationDayService ygUserCultivationDayService;
    @Autowired
    private ScheduleJobService scheduleJobService;
    @Autowired
    private YgBalanceExtraRewardService ygBalanceExtraRewardService;
    @Autowired
    private MailUtil mailUtil;
    @Autowired
    private YgAgentInviteRecordService ygAgentInviteRecordService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private WxSmallMessageService wxSmallMessageService;
    @Autowired
    private PreBalanceHandler preBalanceHandler;

    private final static ExecutorService executorService = Executors.newFixedThreadPool(3);

    @Override
    public void preBalanceTask() {
        TaskMethod task = TaskMethod.PreBalanceTask;
        ygTaskTimeService.execute(task, task.getCode(), new YgTaskTimeTemplate() {

            @Override
            public void execute(Date endDate) {
                System.out.println("开始执行【预收入】任务，runtime--->" + DateConvertUtils.formatDateTime(endDate));
                Date startDate = DateConvertUtils.addMinute(endDate, -task.getCode());

                List<YgOrder> orderList = ygOrderService.findByPaidTimeHasDetail(startDate, endDate, null,
                        OrderStatus.WaitingCheck, OrderStatus.WaitingSend,
                        OrderStatus.WaitingSign, OrderStatus.TradeSuccess);
                List<YgReturnOrder> returnList = ygReturnOrderService.findByReturnStatusHasDetail(startDate,
                        endDate, null, ReturnType.Return, ReturnStatus.Complete);
                doPreBalanceTask(orderList, returnList);
                System.out.println("执行【预收入】任务结束，runtime--->" + DateConvertUtils.formatDateTime(endDate));
            }

        });
    }

    @Override
    public void doPreBalanceTask(List<YgOrder> orderList, List<YgReturnOrder> returnList) {
        List<YgUserBalanceDetail> orderPreBalance = preBalanceHandler.doOrderPreBalanceNotSpitPlatform(orderList);

        List<YgUserBalanceDetail> returnPreBalance = preBalanceHandler.doReturnPreBalance(returnList, orderPreBalance);

        List<YgUserBalanceDetail> detailList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(orderPreBalance)) {
            detailList.addAll(orderPreBalance);
        }
        if (CollectionUtils.isNotEmpty(returnPreBalance)) {
            detailList.addAll(returnPreBalance);
        }

        List<YgUserBalanceDetail> resultList = removeExitDetail(detailList, BalanceType.PreIncome);
        Set<Long> set = resultList.stream().map(YgUserBalanceDetail::getUserId).collect(Collectors.toSet());

        int i = ygUserBalanceService.addBalacneDetailByBatch(resultList);
        if (i > 0) {
            ygUserBalanceService.resetUserBalance(BalanceType.PreIncome, new ArrayList<>(set));
            doTradeCloseOrder(returnList);
            try {
                sendBalanceMsg(resultList, BalanceType.PreIncome);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 处理交易已关闭订单的预收入记录
     *
     * @param returnList
     */
    private void doTradeCloseOrder(List<YgReturnOrder> returnList) {
        if (CollectionUtils.isEmpty(returnList)) {
            return;
        }
        executorService.execute(() -> {
            List<Long> closeOrderIdList = new ArrayList<>();
            for (YgReturnOrder ygReturnOrder : returnList) {
                if (ygReturnOrderService.isAllReturn(ygReturnOrder.getOrderId())) {
                    closeOrderIdList.add(ygReturnOrder.getOrderId());
                }
            }
            List<YgReturnOrder> returnOrderList = ygReturnOrderService.findByOrderIdList(closeOrderIdList, ReturnType.Return); // 指定订单编号下所有退款单
            List<String> list = returnOrderList.stream().map(YgReturnOrder::getReturnCode).collect(Collectors.toList());
            list.addAll(closeOrderIdList.stream().map(Object::toString).collect(Collectors.toList()));
            ygUserBalanceDetailService.updateIsGivedByOrderIdList(Boolean.TRUE, list);
        });
    }

    private List<YgUserBalanceDetail> removeExitDetail(List<YgUserBalanceDetail> detailList, BalanceType balanceType) {
        Map<String, List<YgUserBalanceDetail>> collect = detailList.stream().collect(Collectors.groupingBy(YgUserBalanceDetail::getOrderId));

        for (Entry<String, List<YgUserBalanceDetail>> entry : collect.entrySet()) {
            String orderId = entry.getKey();
            List<YgUserBalanceDetail> exitList = ygUserBalanceDetailService.findDetailByOrderDetail(balanceType, null, null, orderId, null);
            detailList.removeAll(exitList);
        }
        return detailList;

    }

    @Override
    public void sendBalanceMsg(List<YgUserBalanceDetail> detailList, BalanceType balanceType) {
        sendBalanceMsgBySms(detailList, balanceType);

        if (BalanceType.PreIncome.equals(balanceType)) {
            // 壹家店只发预收入
            List<YgUserBalanceDetail> listByYijiadian = detailList.stream()
                    .filter(o -> Constant.YIJIADIAN_PLATFORM_NO.equals(o.getPlatformNo()))
                    .collect(Collectors.toList());
            sendBalanceMsgYijiadian(listByYijiadian);
        }
    }

    private void sendBalanceMsgYijiadian(List<YgUserBalanceDetail> detailList) {
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        Map<Long, List<YgUserBalanceDetail>> collect = detailList.stream()
                .filter(o -> o.getIncomePayPrice().compareTo(BigDecimal.ZERO) > 0)
                .collect(Collectors.groupingBy(YgUserBalanceDetail::getUserId));
        if (MapUtils.isEmpty(collect)) {
            return;
        }
        collect.forEach((userId, detals) -> {
            Map<String, List<YgUserBalanceDetail>> collect2 = detals.stream()
                    .collect(Collectors.groupingBy(YgUserBalanceDetail::getOrderId));
            if (MapUtils.isEmpty(collect)) {
                return;
            }
            collect2.forEach((orderId, details2) -> {
                BigDecimal incomePrice = BigDecimal.ZERO;
                for (YgUserBalanceDetail detail : details2) {
                    incomePrice = incomePrice.add(detail.getIncomePayPrice());
                }
                YgUserBalanceDetail detail = details2.get(0);
                if (orderId.startsWith("R")) {
                    YgReturnOrder returnOrder = ygReturnOrderService.findByReturnCode(orderId);
                    orderId = returnOrder.getOrderId().toString();
                }
                YgOrder order = ygOrderService.findByOrderId(Long.valueOf(orderId));
                wxSmallMessageService.sendIncomeReceiptMsg(detail.getUserId(), detail.getPlatformNo(),
                        incomePrice, orderId, order.getTotalPrice());
            });
        });
	}

    public void sendBalanceMsgBySms(List<YgUserBalanceDetail> detailList, BalanceType balanceType) {
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        Map<Long, List<YgUserBalanceDetail>> mapByUser = detailList.stream()
                .collect(Collectors.groupingBy(YgUserBalanceDetail::getUserId));

        for (Entry<Long, List<YgUserBalanceDetail>> userEntry : mapByUser.entrySet()) {
            List<YgUserBalanceDetail> userDetails = userEntry.getValue();
            Long userId = userEntry.getKey();
            YgUser user = ygUserService.findById(userId);
            /*BigDecimal price = ZERO;*/

            Map<String, List<YgUserBalanceDetail>> mapByOrder = userDetails.stream()
                    .collect(Collectors.groupingBy(YgUserBalanceDetail::getOrderId));

            for (Entry<String, List<YgUserBalanceDetail>> orderEntry : mapByOrder.entrySet()) {
                List<YgUserBalanceDetail> orderDetails = orderEntry.getValue();
                /*if (balanceType.equals(BalanceType.PreIncome)) {

                    price = orderDetails.stream().map(YgUserBalanceDetail::getIncomePayPrice).reduce(ZERO, BigDecimal::add);
                } else {
                    price = orderDetails.stream().map(YgUserBalanceDetail::getBalancePrice).reduce(ZERO, BigDecimal::add);

                }*/

                YgUser u = ygUserService.findById(userId);
                String title = "亲，您有新的" + balanceType.getTitle() + "了。";
                String remark = "可以到\"预计成长基金\"查看哦";

                if (balanceType.equals(BalanceType.Balance)) {
                    if (u.getUserType().equals(UserType.UserAgent) || u.getUserType().equals(UserType.Group)) {

                        remark = "可以到\"可提现金额\"查看哦";
                    } else {
                        remark = "可以到\"成长基金\"查看哦";
                    }

                    // 短信通知，仅通知代理的预计收入
                    continue;
                } else {
                    if (u.getUserType().equals(UserType.UserAgent) || u.getUserType().equals(UserType.Group)) {
                        if (Constant.YIJIADIAN_PLATFORM_NO.equals(orderDetails.get(0).getPlatformNo())) {
                            remark = "可以到\"壹家店 -> 收益明细\"查看哦";
                        } else {
                            remark = "可以到\"壹果商城 -> 预计收入\"查看哦";
                        }
                    } else {
                        remark = "可以到\"预计成长基金\"查看哦";

                        // 短信通知，仅通知代理的预计收入
                        continue;
                    }
                }
                /*final BigDecimal balancePrice = price;*/
                final String sendRemark = remark;

                executorService.execute(new Runnable() {
                    public void run() {
                        // 短信通知，仅通知代理的预计收入
                        if (YgStringUtils.isChinaPhoneLegal(user.getUserName())) {
                            smsService.sendSms(user.getUserName(), title + sendRemark);
                        }
                    }
                });

            }
        }

    }

    /*private List<YgUserBalanceDetail> doReturnPreBalance(List<YgReturnOrder> returnList) {
        List<YgUserBalanceDetail> returnBalanceList = new ArrayList<>();
        // 循环各个退货单
        for (YgReturnOrder ro : returnList) {
            if (ro.getOrderId().toString().startsWith("17")) {
                // 17年的订单不做处理
                continue;
            }
            // 获取当前退货单对应的订单相关预收入
            List<YgUserBalanceDetail> ubds = ygUserBalanceDetailService.
                    findDetailByOrderDetail(BalanceType.PreIncome, null, null, ro.getOrderId().toString(),
                    null);
            // 筛选出 消费奖励（自买）的预收入rewardlist
            List<YgUserBalanceDetail> rewardlist = ubds.stream()
                    .filter(ubd -> ubd.getRebateType().equals(RebateType.Reward)).collect(Collectors.toList());
            // 除了消费奖励外的其它预收入ubds
            ubds.removeAll(rewardlist);

            // 循环各个退货商品
            for (YgReturnOrderDetail rod : ro.getReturnOrderDetails()) {

                if (CollectionUtils.isNotEmpty(ubds)) {
                    // 预收入ubds 中，找到当前退货明细相关的预收入
                    List<YgUserBalanceDetail> collect = ubds.stream().filter(d -> d.getOrderDetailId().equals(rod.getOrderDetailId()))
                            .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(collect)) {
                        // 循环 当前退货商品的预收入
                        for (YgUserBalanceDetail ubd : collect) {
                            // 如果明细是多次退货，会存在已退的预收入
                            List<YgUserBalanceDetail> returned = ygUserBalanceDetailService.
                                    findByOrderDetailId(BalanceType.PreIncome, null, null, "return",
                                    ubd.getOrderDetailId());
                            // 当前类型奖励的预收入奖励
                            BigDecimal lastOrderPrice = ubd.getOrderPrice();
                            if (CollectionUtils.isNotEmpty(returned)) {
                                // 如果以前已经退过，就把剩下可退的预收入计算出来
                                BigDecimal returnPrice = returned.stream().filter(d -> d.getRebateType().equals(ubd.getRebateType()))
                                        .map(YgUserBalanceDetail::getOrderPrice).reduce(ZERO, BigDecimal::add);
                                lastOrderPrice = lastOrderPrice.subtract(returnPrice);
                            }
                            YgUserBalanceDetail detail = ubd.clone();
                            BigDecimal skuSharePrice = getSkuSharePrice(ubd.getOrderPrice(), rod.getQuantity(), rod.getAmount());
                            if (skuSharePrice.compareTo(lastOrderPrice) > 0) {
                                skuSharePrice = lastOrderPrice;
                            }
                            if (!detail.getRebateType().equals(RebateType.FirstAward)) {
                                BigDecimal incomePayPrice = skuSharePrice.multiply(detail.getCommissionRate()).multiply(MINUS_ONE).setScale(1,
                                        BigDecimal.ROUND_HALF_UP);
                                detail.setIncomePayPrice(incomePayPrice);
                                detail.setOrderPrice(skuSharePrice);
                            }
                            detail.setOrderId(ro.getReturnCode());
                            detail.setOperationType(OperationType.Return);
                            detail.setOperation(OperationType.Return.getTitle());
                            detail.setCreateTime(new Date());
                            returnBalanceList.add(detail);
                        }

                    }
                }
            }
            BigDecimal refundPrice = ZERO;
            // 处理 消费奖励
            if (CollectionUtils.isNotEmpty(rewardlist)) {
                YgUserBalanceDetail reward = rewardlist.get(0);
                List<YgUserBalanceDetail> returned = ygUserBalanceDetailService.
                        findBalanceReturnDetailByOrderId(BalanceType.PreIncome, RebateType.Reward,
                        ro.getOrderId());
                BigDecimal lastOrderPrice = reward.getOrderPrice();

                if (CollectionUtils.isNotEmpty(returned)) {
                    BigDecimal returnPrice = returned.stream().filter(d -> d.getRebateType().equals(reward.getRebateType()))
                            .map(YgUserBalanceDetail::getOrderPrice)
                            .reduce(ZERO, BigDecimal::add);
                    lastOrderPrice = lastOrderPrice.subtract(returnPrice);
                }
                BigDecimal thisReturnPrice = getReturnPrice(ro);
                if (thisReturnPrice.compareTo(lastOrderPrice) > 0) {
                    thisReturnPrice = lastOrderPrice;
                }
                refundPrice = thisReturnPrice;
            }
            if (refundPrice.compareTo(ZERO) > 0) {
                if (CollectionUtils.isNotEmpty(rewardlist)) {
                    YgUserBalanceDetail reward = rewardlist.get(0);
                    YgUserBalanceDetail clone = reward.clone();
                    clone.setOrderId(ro.getReturnCode());
                    BigDecimal incomePayPrice = refundPrice.multiply(clone.getCommissionRate())
                            .setScale(1, BigDecimal.ROUND_HALF_UP)
                            .multiply(MINUS_ONE);
                    clone.setIncomePayPrice(incomePayPrice);
                    clone.setOrderPrice(refundPrice);
                    clone.setCreateTime(new Date());
                    clone.setOperationType(OperationType.Return);
                    clone.setOperation(OperationType.Return.getTitle());
                    returnBalanceList.add(clone);
                }
            }
        }
        return returnBalanceList;

    }

    private BigDecimal getReturnPrice(YgReturnOrder ro) {
        YgOrder order = ygOrderService.findOrderDetailByOrderId(ro.getOrderId());
        if (Constant.YIJIADIAN_PLATFORM_NO.equals(order.getPlatformNo())) {
            order = getProductSharePrice(order);
        } else {
            order = getOrderSharePrice(order);
        }

        BigDecimal returnPrice = ZERO;
        for (YgReturnOrderDetail rod : ro.getReturnOrderDetails()) {
            for (YgOrderDetail od : order.getOrderDetail()) {
                if (rod.getSourceSkuId().equals(od.getSkuId()) && od.getSalePrice().compareTo(ZERO) > 0) {
                    if (od.getQuantity().compareTo(rod.getAmount()) <= 0) {
                        returnPrice = returnPrice.add(od.getOrderSharePrice());
                    } else {
                        BigDecimal price = od.getOrderSharePrice()
                                .divide(new BigDecimal(od.getQuantity()), 1, BigDecimal.ROUND_HALF_UP)
                                .multiply(BigDecimal.valueOf(rod.getAmount()));
                        returnPrice = returnPrice.add(price);
                    }

                }

            }

        }
        return returnPrice;

    }

    private BigDecimal getSkuSharePrice(BigDecimal itemPrice, Long totalAmount, Long subAmount) {
        if (itemPrice != null) {
            if (totalAmount.compareTo(subAmount) > 0) {
                return itemPrice.divide(new BigDecimal(totalAmount)).multiply(new BigDecimal(subAmount));
            } else {
                return itemPrice;
            }

        }
        return null;
    }*/

    /**
     * 计算预计收入
     * <p>
     * 1、推荐奖励。代理下单，给邀请用户（代理不包括自己）2%推荐返利；
     * 2、分享奖励。普通用户下单，给分享用户（代理）5%-10%分享返利；
     *
     * @param orderList
     * @return
     */
    /*private List<YgUserBalanceDetail> doOrderPreBalance(List<YgOrder> orderList) {
        List<YgUserBalanceDetail> detailList = null;
        for (YgOrder order : orderList) {
            if (order.getTotalPrice().compareTo(ZERO) == 0) {
                continue;
            }
            if (CollectionUtils.isEmpty(detailList)) {
                detailList = new ArrayList<>();
            }

            YgUser user = ygUserService.findById(order.getUserId());
            YgUser shareUser;
            YgUser foreverUser = null;
			
			YgUser foreverUser = ygUserService.findBySourceCode(user.getFromCode());
			YgUser shareUser = ygUserService.findBySourceCode(order.getSourceCode());

            YgAgentInviteRecord agentInviteRecord = ygAgentInviteRecordService.findValidByReceiveUserId(user.getId());
            if (agentInviteRecord != null && agentInviteRecord.inValidTime(order.getPaidTime())) { // 下单用户是代理 或者下单时间在被取消时间之前
                shareUser = null; // 无任何分享奖励
                if (agentInviteRecord.getUserId().compareTo(user.getId()) != 0) { // 被他人邀请成为代理，给邀请人推荐奖励
                    foreverUser = ygUserService.findById(agentInviteRecord.getUserId());
                }
            } else {
                shareUser = ygUserService.findBySourceCode(order.getSourceCode());
            }

            List<BalanceDetailForTask> detailModel = preBalancePretreatment(order);

            if (foreverUser != null) {
                if (foreverUser.isUserAgent() || foreverUser.isUserGroup()) { // 下单用户的推荐用户为代理，给推荐人推荐奖励
                    List<YgUserBalanceDetail> foreverUserDetails =
                            this.getPreBalanceDetailList(detailModel, RebateType.Forever, OperationType.Forever,
                                foreverUser.getId(), "foreverUser");
                    detailList.addAll(foreverUserDetails);
                }
            }

            if (shareUser != null) {
                if (shareUser.isUserAgent() || shareUser.isUserGroup()) { // 分享人为代理或团长，给分享奖励
                    List<YgUserBalanceDetail> shareUserDetails = this.getPreBalanceDetailList(detailModel, RebateType.Share, OperationType.Share,
                            shareUser.getId(), "shareUser");
                    detailList.addAll(shareUserDetails);
                }
            }

            YgUser groupHead = ygUserService.findGroupHead(user.getGroupTag());
            if (groupHead != null && !groupHead.getId().equals(user.getId())
                    && (shareUser == null || (!groupHead.getId().equals(shareUser.getId()) && !shareUser.isUserAgent() && !shareUser.isUserGroup()))) {
                // 下单人是团成员，分享人不是该团员团长 且分享人不是代理和团长。 给该成员团长分享奖励，且下单人不是团长
                List<YgUserBalanceDetail> groupHeadDetails = this.getPreBalanceDetailList(detailModel, RebateType.Share, OperationType.Share, groupHead.getId(),
                        "groupHead");
                detailList.addAll(groupHeadDetails);
            }
			
			// 撤销代理自己下单的分享奖励
			if ((user.isUserAgent() || user.isUserGroup())) {
				if ((shareUser == null || (!shareUser.isUserAgent() && !shareUser.isUserGroup()))) {
					// 下单人也是代理且分享人不是代理
					List<YgUserBalanceDetail> agentDetails = this.getPreBalanceDetailList(detailModel, RebateType.Share, OperationType.Share, user.getId(),
							"agent");
					detailList.addAll(agentDetails);
				}

			}
			
			// 撤销代理的消费奖励
			doPreReward(user, order.getOrderId().toString(), order.getTotalPrice(), "Order", detailList);
        }
        return detailList;

    }*/

    /**
     * 根据销售平台把订单拆分为壹果订单和壹家店订单，返利逻辑分开处理
     * @param orderList
     * @return
     */
    /*private List<YgUserBalanceDetail> doOrderPreBalance201904(List<YgOrder> orderList) {
        List<YgUserBalanceDetail> detailList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(orderList)) {
            // 壹果订单
            List<YgOrder> orderListAtYiigoo = orderList.stream().filter(o -> !Constant.YIJIADIAN_PLATFORM_NO.equals(o.getPlatformNo()))
                    .collect(Collectors.toList());
            detailList.addAll(doOrderPreBalance201811(orderListAtYiigoo));
            // 壹家店订单
            List<YgOrder> orderListAtYijiadian = orderList.stream().filter(o -> Constant.YIJIADIAN_PLATFORM_NO.equals(o.getPlatformNo()))
                    .collect(Collectors.toList());
            detailList.addAll(doOrderPreBalanceByYijiadian(orderListAtYijiadian));
        }
        return detailList;
    }*/

    /**
     * 壹家店代理奖励规则：
     * 1、代理自买奖励，100%佣金
     * 2、二级粉丝购买奖励，100%佣金
     * 3、三级非代理粉丝购买奖励，90%佣金
     * @param orderList 壹家店订单
     * @return
     */
    /*private List<YgUserBalanceDetail> doOrderPreBalanceByYijiadian(List<YgOrder> orderList) {
        List<YgUserBalanceDetail> detailList = new ArrayList<>();
        if (CollectionUtils.isEmpty(orderList)) {
            return detailList;
        }
        for (YgOrder order : orderList) {
            if (order.getTotalPrice().compareTo(ZERO) == 0) {
                // 0元订单无返利
                continue;
            }

            // 下单人信息
            YgUser user = ygUserService.findById(order.getUserId());
            if (UserType.UserAgent.equals(user.getUserType())) {
                // 下单人为代理，有自买奖励
                setPreBalanceDetailList(detailList, order, RebateType.Reward, OperationType.Reward, user.getId(),
                        "currentUser");
            }

            // 上级邀请人信息
            YgUser inviteUser = getInviteUser(order.getUserId());
            if (inviteUser != null && UserType.UserAgent.equals(inviteUser.getUserType())) {
                // 存在上级邀请人，并上级是代理，给邀请人推荐奖励
                // 下单人为代理时，上级邀请人抽取30%的佣金，否则上级邀请人抽取100%佣金
                if (UserType.UserAgent.equals(user.getUserType())) {
                    order.getOrderDetail().forEach(o ->
                            o.setShareRate(o.getShareRate().multiply(BigDecimal.valueOf(0.3))
                                    .setScale(2, BigDecimal.ROUND_HALF_UP)));
                }
                setPreBalanceDetailList(detailList, order, RebateType.Share, OperationType.Share, inviteUser.getId(),
                        "foreverUser");

                // 下单人为普通用户，并且存在跨级邀请人，跨级邀请人作为代理，可抽取30%的佣金
                if (UserType.Ordinary.equals(user.getUserType())) {
                    YgUser crossInviteUser = getInviteUser(inviteUser.getId());
                    if (crossInviteUser != null && UserType.UserAgent.equals(crossInviteUser.getUserType())) {
                        // 存在跨级邀请人，抽取30%佣金
                        order.getOrderDetail().forEach(o ->
                                o.setShareRate(o.getShareRate().multiply(BigDecimal.valueOf(0.3))
                                        .setScale(2, BigDecimal.ROUND_HALF_UP)));
                        setPreBalanceDetailList(detailList, order, RebateType.Forever, OperationType.Forever, crossInviteUser.getId(),
                                "crossForeverUser");
                    }
                }
            }
        }
        return detailList;
    }

    private YgUser getInviteUser(Long receiveUserId) {
        YgAgentInviteRecord record = ygAgentInviteRecordService.findRecordForYijiandian(receiveUserId);
        if (record != null) {
			return ygUserService.findById(record.getUserId());
        }
		return null;
    }*/

    /**
     * 代理分享给自己推荐的女王，推荐和分享怎么给
     * 只给分享
     * 代理分享给非自己推荐的女王，推荐和分享怎么给
     * 不给
     * 代理分享给非女王，推荐和分享怎么给
     * 只给分享
     *
     * @return List<YgUserBalanceDetail>    返回类型
     * @throws
     * @Title: doOrderPreBalance201811
     * @author （guohao）
     * @date 2018年11月16日 上午10:57:19
     * @version V1.0
     */
    /*private List<YgUserBalanceDetail> doOrderPreBalance201811(List<YgOrder> orderList) {
        List<YgUserBalanceDetail> detailList = new ArrayList<>();
        if (CollectionUtils.isEmpty(orderList)) {
            return detailList;
        }
        for (YgOrder order : orderList) {
            if (order.getTotalPrice().compareTo(ZERO) == 0) {
                continue;
            }
            YgUser user = ygUserService.findById(order.getUserId());
            //下单人为代理 只有消费奖励
            if (user.isUserAgent()) {
				setPreBalanceDetailList(detailList, order, RebateType.Reward, OperationType.Reward, user.getId(), "currentUser");
				continue;
            }
            YgUser shareUser = ygUserService.findBySourceCode(order.getSourceCode());
            if (user.getLevel() == 10) {
                YgUserMember userMember = ygUserMemberService.findByUserId(user.getId());
                if (!userMember.getUserId().equals(userMember.getInviterId())) {
                    YgUser inviter = ygUserService.findById(userMember.getInviterId());
                    if (UserType.UserAgent.equals(inviter.getUserType())) {
                        shareUser = inviter;
                    }
                }
            }
            if (shareUser == null) {
                continue;
            }
            //分享奖励
            //1。分享人为代理，下单人为女王（且分享人邀请的女王）
            //2。分享人为代理，下单人为普通用户，
            YgAgentInviteRecord agentInviteRecord = ygAgentInviteRecordService.findValidByReceiveUserId(shareUser.getId());
            // 分享人是代理 或者下单时间在被取消时间之前
            if (agentInviteRecord != null && agentInviteRecord.inValidTime(order.getPaidTime())) {
                if (user.getLevel() == 10) {
                    YgUserMember userMember = ygUserMemberService.findByUserId(user.getId());
                    if (!userMember.getInviterId().equals(shareUser.getId())) {
                        continue;
                    }
                }
            } else {
                continue;
            }
            setPreBalanceDetailList(detailList, order, RebateType.Share, OperationType.Share, shareUser.getId(), "shareUser");
        }
        return detailList;
    }*/

    @Override
	public void setPreBalanceDetailList(List<YgUserBalanceDetail> detailList, YgOrder order, RebateType rebateType,
                                         OperationType operationType, Long userId, String createBy) {
		List<BalanceDetailForTask> detailModel = preBalancePretreatment(order);
		List<YgUserBalanceDetail> shareUserDetails = this.getPreBalanceDetailList(detailModel, rebateType, operationType,
				userId, createBy, order.getPlatformNo());
		detailList.addAll(shareUserDetails);
	}

	/*private void doPreReward(YgUser user, String orderId, BigDecimal orderPrice, String orderType, List<YgUserBalanceDetail> detailList) {
		Boolean exit = ygUserBalanceDetailService.exitBalanceDetailByOrderId(BalanceType.PreIncome, RebateType.Reward, orderId, user.getId());
		if (!exit) {
			// 用户下单，发货后15天奖励用户成长基金。
			BigDecimal rate = new BigDecimal("0.01");
			if (user.getLevel().compareTo(10) == 0) {
				rate = new BigDecimal("0.02");
			}
			BigDecimal inCome = orderPrice.multiply(rate).setScale(2, BigDecimal.ROUND_HALF_UP);
			if (orderType.equals("Return")) {
				inCome = inCome.multiply(MINUS_ONE);
			}

			YgUserBalanceDetail rewardDetail = new YgUserBalanceDetail();
			rewardDetail.setOperation(OperationType.Reward.getTitle());
			rewardDetail.setOperationType(OperationType.Reward);
			rewardDetail.setIncomePayPrice(inCome);
			rewardDetail.setOrderId(orderId);
			rewardDetail.setOrderDetailId(REWARD_ODID);
			rewardDetail.setCreateTime(new Date());
			rewardDetail.setCreateBy("system;" + user.getLevel());
			rewardDetail.setPriceType(BalanceType.PreIncome);
			rewardDetail.setOrderPrice(orderPrice);
			rewardDetail.setUserId(user.getId());
			rewardDetail.setRebateType(RebateType.Reward);
			rewardDetail.setCommissionRate(rate);
			detailList.add(rewardDetail);
		}
	}

    private List<YgUserBalanceDetail> getPreBalanceDetailList(List<BalanceDetailForTask> detailModel,
                                                              RebateType rebateType, OperationType operationType,
                                                              Long userId, String createBy) {
        return getPreBalanceDetailList(detailModel, rebateType, operationType, userId, createBy, null);
    }*/

	@Override
    public List<YgUserBalanceDetail> getPreBalanceDetailList(List<BalanceDetailForTask> detailModel,
                                                             RebateType rebateType, OperationType operationType,
                                                             Long userId, String createBy, String platformNo) {
        List<YgUserBalanceDetail> balanceDetailList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(detailModel)) {
            for (BalanceDetailForTask item : detailModel) {
                YgUserBalanceDetail balanceDetail = new YgUserBalanceDetail();
                balanceDetail.setUserId(userId);
                balanceDetail.setPriceType(BalanceType.PreIncome);
                balanceDetail.setRebateType(rebateType);
                balanceDetail.setOperationType(operationType);
                balanceDetail.setOperation(operationType.getTitle());
                balanceDetail.setIncomePayPrice(item.getBalancePrice(rebateType, platformNo));
                balanceDetail.setOrderId(item.getOrderId());
                balanceDetail.setOrderDetailId(item.getOrderDetailId());
                balanceDetail.setProductName(item.getProductName());
                balanceDetail.setOrderPrice(item.getSharePrice());
                balanceDetail.setCommissionRate(item.getRate(rebateType, platformNo));
                balanceDetail.setRemark("预收入");
                balanceDetail.setCreateTime(new Date());
                balanceDetail.setCreateBy(createBy);
                balanceDetail.setPlatformNo(platformNo);

                balanceDetailList.add(balanceDetail);
            }
        }
        return balanceDetailList;

    }

    /**
     * 组装预收入信息集
     * 所有推荐奖励2%
     * 2018-05-21
     *
     * @param order
     * @return
     */
    @Override
    public List<BalanceDetailForTask> preBalancePretreatment(YgOrder order) {
        YgOrder ygOrder;
        if (Constant.YIJIADIAN_PLATFORM_NO.equals(order.getPlatformNo())) {
        	ygOrder = this.getProductSharePrice(order);
		} else {
			ygOrder = this.getOrderSharePrice(order);
		}
        List<YgOrderDetail> orderDetail = ygOrder.getOrderDetail();
        List<BalanceDetailForTask> list = null;
        for (YgOrderDetail detail : orderDetail) {
            if (PromotionType.ManZeng.equals(detail.getPromotionType())) {
                continue;
            }
            BalanceDetailForTask bd = new BalanceDetailForTask(detail.getId(), detail.getSupplierId(), order.getOrderId().toString(),
                    detail.getOrderSharePrice(), detail.getProductName(), detail.getShareRate(), new BigDecimal("0.02"));
            if (list == null) {
                list = new ArrayList<>();
            }

            list.add(bd);
        }
        return list;
    }

    @Override
    public void preBalanceToBalanceTask() {

        TaskMethod task = TaskMethod.PreIncomeToBalanceV2;
        Integer interval = task.getCode();
        ygTaskTimeService.execute(task, interval, new YgTaskTimeTemplate() {

            @Override
            public void execute(Date date) {

            }
        });
    }

    @Override
    public Message doPreToBalance(Long orderId) {
        YgOrder order = ygOrderService.findByOrderId(orderId);
        if (order.getSendTime() == null) {
            return Message.error("订单尚未发货，", orderId);
        }
		/*if (!new Date().after(DateConvertUtils.addDay(order.getSendTime(), 15))) {
			return Message.error("未到触发时间。",
					"now = " + DateConvertUtils.formatDateTime(new Date()) + ";sendTime =" + DateConvertUtils.formatDateTime(order.getSendTime()));
		}*/

        if (order.getPaidTime().before(DateConvertUtils.parse("2018-01-01", DateConvertUtils.DATE_FORMAT))) {
            return Message.error("17年订单不做处理", orderId);
        }
        List<YgReturnOrder> returnList = ygReturnOrderService.findByOrderId(orderId, ReturnType.Return, null);
        return doPreToBalanceBussness(order, returnList, "doPreToBalance");

    }

    private Message doPreToBalanceBussness(YgOrder order, List<YgReturnOrder> returnList, String method) {

        List<YgUserBalanceDetail> orderList = ygUserBalanceDetailService.findDetailByOrderDetail(BalanceType.PreIncome, null, null,
                order.getOrderId().toString(), null);

        if (CollectionUtils.isEmpty(orderList)) {
            return Message.error("该订单没有返利", null);
        }
        List<YgUserBalanceDetail> balanceList = new ArrayList<>();
        BigDecimal lastPrice = order.getTotalPrice();
        List<Long> writeBackDetaiIdlList = new ArrayList<>();
        for (YgReturnOrder returnOrder : returnList) {
            Boolean hasReturn = false;

            if (returnList != null) {
                if (!returnOrder.getReturnStatus().equals(ReturnStatus.Complete) && !returnOrder.getReturnStatus().equals(ReturnStatus.Cancel)
                        && !returnOrder.getReturnStatus().equals(ReturnStatus.Reject)) {
                    // 存在没完成退货单，暂不处理。完成之后再做处理
                    return Message.success("该订单存在未完成退货单订单", null);
                } else {
                    hasReturn = true;
                }
            }

            if (hasReturn) {
                lastPrice = lastPrice.subtract(returnOrder.getRefundPrice());

                List<YgUserBalanceDetail> rturnList = null;
                rturnList = ygUserBalanceDetailService.findDetailByOrderDetail(BalanceType.PreIncome, null, null, returnOrder.getReturnCode(), null);

                for (YgUserBalanceDetail rbd : rturnList) {
                    YgUserBalanceDetail clone = rbd.clone();
                    clone.setBalancePrice(rbd.getIncomePayPrice());
                    clone.setIncomePayPrice(ZERO);
                    clone.setPriceType(BalanceType.Balance);
                    clone.setCreateBy("doPreToBalance");
                    clone.setCreateTime(new Date());
                    clone.setRemark("可提现");
                    balanceList.add(clone);
                    writeBackDetaiIdlList.add(rbd.getId());
                }
            }
        }
        for (YgUserBalanceDetail obd : orderList) {
            YgUserBalanceDetail clone = obd.clone();
            clone.setBalancePrice(clone.getIncomePayPrice());
            clone.setIncomePayPrice(ZERO);
            clone.setPriceType(BalanceType.Balance);
            clone.setCreateBy(method);
            clone.setCreateTime(new Date());
            clone.setRemark("可提现");
            balanceList.add(clone);
            writeBackDetaiIdlList.add(obd.getId());
        }

        List<YgUserBalanceDetail> resultList = removeExitDetail(balanceList, BalanceType.Balance);
        Set<Long> set = resultList.stream().map(ubd -> ubd.getUserId()).collect(Collectors.toSet());

        int i = ygUserBalanceService.addBalacneDetailByBatch(resultList);
        if (i > 0) {
            // 回写预收入明细的是否已给状态
            ygUserBalanceDetailService.updateIsGived(Boolean.TRUE, writeBackDetaiIdlList);
            ygUserBalanceService.resetUserBalance(null, new ArrayList<Long>(set));
            sendBalanceMsg(resultList, BalanceType.Balance);
        }
        return Message.success(null);

    }

    @Override
    public void affiliateUserReport() {
        TaskMethod task = TaskMethod.AffiliateUserReportV2;
        Integer interval = task.getCode();

        ygTaskTimeService.execute(task, interval, new YgTaskTimeTemplate() {

            @Override
            public void execute(Date endDate) throws Exception {
                System.out.println("开始执行【代理用户耕耘报表】任务，runtime--->" + DateConvertUtils.formatDateTime(endDate));
                Date startDate = DateConvertUtils.addMinute(endDate, -interval);
                System.out.println("startDate =" + DateConvertUtils.formatDateTime(startDate) + " ----- endDate =" + DateConvertUtils.formatDateTime(endDate));

                List<YgOrder> orders = ygOrderService.findByPaidTimeHasDetail(startDate, endDate, null);
                if (CollectionUtils.isNotEmpty(orders)) {
                    orders = orders.stream().filter(o -> Constant.YIIGOO_PLATFORM_NO.equals(o.getPlatformNo()))
                            .collect(Collectors.toList());
                }

                List<Long> returnOrderIds = ygReturnOrderService.findOrderIdsByReturn(startDate, endDate, ReturnType.Return, ReturnStatus.Complete);
                logger.info("耕耘成果退货订单" + DateConvertUtils.format(startDate) + ">>>" + DateConvertUtils.format(endDate) + ">>>" + returnOrderIds.toString());
                List<YgOrder> returns = ygOrderService.findRODByOrderId(returnOrderIds, ReturnType.Return, ReturnStatus.Complete);
                if (CollectionUtils.isNotEmpty(returns)) {
                    returns = returns.stream().filter(o -> Constant.YIIGOO_PLATFORM_NO.equals(o.getPlatformNo()))
                            .collect(Collectors.toList());
                }

                List<YgUserCultivationDay> orderList = doOrderShareBussness("order", orders);
                List<YgUserCultivationDay> returnList = doOrderShareBussness("return", returns);

                // 去除 下单与退货同一时间区间 的退货数据
                if (CollectionUtils.isNotEmpty(returnList) && CollectionUtils.isNotEmpty(orderList)) {
                    Iterator<YgUserCultivationDay> it = returnList.iterator();
                    while (it.hasNext()) {
                        YgUserCultivationDay next = it.next();
                        for (YgUserCultivationDay ol : orderList) {
                            if (ol.getUserId().equals(next.getUserId()) && ol.getOrderId().equals(next.getOrderId())) {
                                ol.setReturnPrice(next.getReturnPrice());
                                ol.setTotalPrice(ol.getOrderPrice().subtract(ol.getReturnPrice()));
                                it.remove();
                            }
                        }

                    }
                }

                List<YgUserCultivationDay> exitList = ygUserCultivationDayService.findByDay(startDate, endDate);
                orderList.removeAll(exitList);
                ygUserCultivationDayService.additional(returnList);
                ygUserCultivationDayService.addBatch(orderList);
                System.out.println("执行【代理用户耕耘报表】任务结束，runtime--->" + DateConvertUtils.formatDateTime(endDate));
            }

        });

    }

	/*private List<YgUserCultivationDay> doOrderShareBussness(String orderType, List<YgOrder> orderList) {
		List<YgUserCultivationDay> orderDayList = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(orderList)) {
			orderList.stream().forEach(o -> {
				if (StringUtils.isEmpty(o.getSourceCode())) {
					o.setSourceCode("");
				}
				
			});
			Map<String, List<YgOrder>> collect = orderList.stream().collect(Collectors.groupingBy(YgOrder::getSourceCode));
			for (Entry<String, List<YgOrder>> entry : collect.entrySet()) {
				String key = entry.getKey();
				List<YgOrder> values = entry.getValue();

				YgUser user = ygUserService.findBySourceCode(key);
				for (YgOrder order : values) {

					if (user != null) {
						if (user.getUserType().equals(UserType.Agent) || user.getUserType().equals(UserType.Channel)) {

							doOrderShare(order, user.getId(), orderDayList, orderType);
						} else if (user.getUserType().equals(UserType.UserAgent) || user.getUserType().equals(UserType.Group)) {

							// 分享
							YgAgent agent = ygAgentService.findByRecent(user.getId(), user.getUserType());
							YgAgentInviteRecord agent = ygAgentInviteRecordService.findValidByReceiveUserId(user.getId());
							if (agent != null && agent.inValidTime(order.getPaidTime())) {

								doOrderShare(order, user.getId(), orderDayList, orderType);
							}

						} else {
							doOrderNoShareUser(order, orderDayList, orderType);
						}

					} else {
						doOrderNoShareUser(order, orderDayList, orderType);
					}
				}
			}
		}
		return orderDayList;
	}

	private void doOrderNoShareUser(YgOrder order, List<YgUserCultivationDay> orderDayList, String orderType) {
		YgUser orderUser = ygUserService.findById(order.getUserId());
		if (orderUser == null) {
			return;
		}
		// 用户是代理
		if (orderUser.isUserAgent() || orderUser.isUserGroup()) {

			this.doOrderShare(order, orderUser.getId(), orderDayList, orderType);
		} else {
			YgUser head = ygUserService.findGroupHead(orderUser.getGroupTag());
			if (head != null) {
				this.doOrderShare(order, head.getId(), orderDayList, orderType);
			}
		}

	}*/

    private List<YgUserCultivationDay> doOrderShareBussness(String orderType, List<YgOrder> orderList) {
        List<YgUserCultivationDay> orderDayList = new ArrayList<>();
        if (CollectionUtils.isEmpty(orderList)) {
            return orderDayList;
        }
        doOrderSourceCodeBussness(orderList);
        Map<String, List<YgOrder>> collect = orderList.stream().collect(Collectors.groupingBy(YgOrder::getSourceCode));
        for (Entry<String, List<YgOrder>> entry : collect.entrySet()) {
            YgUser sourceUser = ygUserService.findBySourceCode(entry.getKey());
            if (sourceUser == null) {
                continue;
            }
            YgAgentInviteRecord sourceAgent = ygAgentInviteRecordService.findValidByReceiveUserId(sourceUser.getId());
            for (YgOrder order : entry.getValue()) {
                switch (sourceUser.getUserType()) {
                    case Agent: // 代理商
                    case Channel: // 渠道
                    case Group: // 团长
                        doOrderShare(order, sourceUser.getId(), orderDayList, orderType);
                        break;
                    default:
                        if (sourceAgent != null && sourceAgent.inValidTime(order.getPaidTime())) { // 代理
                            doOrderShare(order, sourceUser.getId(), orderDayList, orderType);
                        }
                        break;
                }
            }
        }
        return orderDayList;
    }

    /**
     * 代理用户或者团长下单，耕耘成果算下单用户的（无论是不是有分享人）
     *
     * @param orderList
     */
    private void doOrderSourceCodeBussness(List<YgOrder> orderList) {
        for (YgOrder order : orderList) {
            YgUser orderUser = ygUserService.findById(order.getUserId());
            YgAgentInviteRecord agent = ygAgentInviteRecordService.findValidByReceiveUserId(orderUser.getId());
            if (agent != null && agent.inValidTime(order.getPaidTime())) { // 下单用户为代理
                order.setSourceCode(orderUser.getSourceCode());
            } else {
                YgUser head = ygUserService.findGroupHead(orderUser.getGroupTag());
                if (head != null) { // 下单用户为团长
                    order.setSourceCode(head.getSourceCode());
                } else if (StringUtils.isBlank(order.getSourceCode())) {
                    order.setSourceCode("");
                }
            }
        }
    }

    /**
     * 计算分享订单耕耘成果（包括第三方商品）
     * 2018-05-21
     *
     * @param order
     * @param userId
     * @param orderDayList
     * @param orderType
     */
    private void doOrderShare(YgOrder order, Long userId, List<YgUserCultivationDay> orderDayList, String orderType) {
        BigDecimal orderPrice = ZERO;
        BigDecimal returnPrice = ZERO;

		/*Date date = DateConvertUtils.parse("2018-01-01", DateConvertUtils.DATE_FORMAT);
		Boolean onlyYiigoo = true;
		if (order.getPaidTime().before(date)) {
			onlyYiigoo = false;
		}*/
        boolean onlyYiigoo = false;

        YgUserCultivationDay day = new YgUserCultivationDay();
        Date dateStart = DateConvertUtils.getDateStart(order.getPaidTime());
        orderPrice = this.getPaidPrice(order, onlyYiigoo);
        if (orderType.equals("return")) {
            returnPrice = this.getReturnPrice(order, onlyYiigoo);

            day.setUpdateBy("return");
            day.setUpdateTime(new Date());
            day.setRemark("退货扣减");
        }

        day.setUserId(userId);
        day.setOrderId(order.getOrderId());
        day.setOrderPrice(orderPrice);
        day.setReturnPrice(returnPrice);
        day.setTotalPrice(day.getOrderPrice().subtract(day.getReturnPrice()));
        day.setDay(dateStart);

        orderDayList.add(day);

    }

    @Override
    public Message reduceBalance(String returnCode, Long orderId) {

        YgOrder order = ygOrderService.findByOrderId(orderId);
        if (order.getSendTime() == null) {
            return Message.error("订单尚未发货，", orderId);
        }
        List<YgReturnOrder> list = ygReturnOrderService.findByReturnStatusHasDetail(null, null, returnCode, ReturnType.Return, ReturnStatus.Complete);
        if (CollectionUtils.isNotEmpty(list)) {

            return this.doPreToBalanceBussness(order, list, "reduceBalance");
        }
        return Message.error("");
    }

    @Override
    public void calculateExtraRewards() {

        Date month = DateConvertUtils.addMonth(new Date(), -1);
        Date start = DateConvertUtils.getMonthStartDate(month);
        Date end = DateConvertUtils.getMonthEndDate(month);

        Date now = new Date();
        List<YgUserCultivationDay> list = ygUserCultivationDayService.getSumGroupByUserId(start, end);
        List<YgBalanceExtraReward> result = new ArrayList<>();
        for (YgUserCultivationDay day : list) {
            BigDecimal price = day.getTotalPrice();
            Long userId = day.getUserId();
			/*if (price.compareTo(new BigDecimal("3000.00")) < 0) {
				continue;
			}
			Map<String, BigDecimal> map = this.getExtraRewardInfo(price);
			BigDecimal gearRate = map.get("gearRate");
			BigDecimal gearPrice = map.get("gearPrice");*/

            if (price.compareTo(new BigDecimal("5000.00")) < 0) {
                continue;
            }
            if (!ygUserService.isUserAgent(userId)) {
                continue;
            }
            BigDecimal gearRate = new BigDecimal("0.05");
            BigDecimal gearPrice = new BigDecimal("5000.00");

            YgBalanceExtraReward reward = new YgBalanceExtraReward();
            reward.setUserId(userId);
            reward.setUserName(day.getUserName());
            reward.setOrderPrice(price);
            reward.setGearRate(gearRate);
            reward.setGearPrice(gearPrice);
            reward.setRewardPrice(price.multiply(gearRate).setScale(2, BigDecimal.ROUND_HALF_UP));
            reward.setCreateTime(now);
            reward.setHasGaved(false);
            reward.setMonth(DateConvertUtils.getMonth(month));
            reward.setStatus(DataStatus.Valid);
            result.add(reward);

        }
        int i = ygBalanceExtraRewardService.addBatch(result);
        this.sendBalanceExtraRewardMall(result);
        System.out.println(i);
        ygTaskTimeService.saveOrUpdate("calculateExtraRewards", new Date(), "执行成功");
    }

    private void sendBalanceExtraRewardMall(List<YgBalanceExtraReward> list) {
        if (!CollectionUtils.isEmpty(list)) {
            Integer month = list.get(0).getMonth();
            String to = "guohao@yiigoo.com,xueming@yiigoo.com,jiangyunbo@yiigoo.com,sunshuo@yiigoo.cn";
            StringBuffer str = new StringBuffer();
            str.append(
                    "<html><head><style>.table-d table{ background:#000;font-size:14px} .table-d table td{ background:#FFF} h5{width: auto;margin-right: 20px} .title{display: flex;line-height: 10px}");
            str.append("</style></head><body>");
            str.append("<div class='table-d'>");
            str.append("<table width='800' border='0' cellspacing='1' cellpadding='0'><tr><td width='15%'>用户名</td>" + "<td width='15%'>月份</td>"
                    + "<td width='15%'>耕耘成果</td>" + "<td width='15%'>档位金额</td>" + "<td width='15%'>档位比例</td>" + "<td width='15%'>奖励金额</td></tr>");
            for (YgBalanceExtraReward l : list) {
                str.append("<tr><td>" + l.getUserName() + "</td>");
                str.append(" <td>" + l.getMonth() + "</td>");
                str.append(" <td>" + l.getOrderPrice() + "</td>");
                str.append(" <td>" + l.getGearPrice() + "</td>");
                str.append(" <td>" + l.getGearRate() + "</td>");
                str.append("<td>" + l.getRewardPrice() + "</td></tr>");
            }
            str.append("</table>");
            System.out.println(str.toString());
            try {
                mailUtil.sendWithHtml(to.split(","), month + "月份 代理额外奖励名单", str.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

	/*private void gaveExtra(List<YgUserBalanceDetail> result) {
		if (CollectionUtils.isNotEmpty(result)) {
			List<Long> userIds = result.stream().map(ubd -> ubd.getUserId()).collect(Collectors.toList());
			ygUserBalanceService.addBalacneDetailByBatch(result);
			ygUserBalanceService.resetUserBalance(BalanceType.Balance, userIds);
			this.sendBalanceMsg(result, BalanceType.Balance);
		}
	}*/

	/*private YgUserBalanceDetail bulidBalanceDetail(BigDecimal orderPrice, BigDecimal rate, Long userId) {
		YgUserBalanceDetail balanceDetail = new YgUserBalanceDetail();
		balanceDetail.setUserId(userId);
		balanceDetail.setPriceType(BalanceType.Balance);
		balanceDetail.setRebateType(RebateType.Reward);
		balanceDetail.setOperationType(OperationType.ExtraReward);
		balanceDetail.setOperation(OperationType.ExtraReward.getTitle());
		balanceDetail.setIncomePayPrice(ZERO);
		balanceDetail.setBalancePrice(orderPrice);
		balanceDetail.setOrderId("0");
		balanceDetail.setOrderDetailId(0L);
		balanceDetail.setOrderPrice(orderPrice.multiply(rate));
		balanceDetail.setCommissionRate(rate);
		balanceDetail.setRemark("额外奖励");
		balanceDetail.setCreateTime(new Date());
		balanceDetail.setCreateBy("ExtraReward");

		return balanceDetail;
	}*/

	/*private Map<String, BigDecimal> getExtraRewardInfo(BigDecimal price) {
		BigDecimal firstGear = new BigDecimal("3000.00");
		BigDecimal secondGear = new BigDecimal("10000.00");
		BigDecimal thirdGear = new BigDecimal("20000.00");
		BigDecimal fourthGear = new BigDecimal("30000.00");
		BigDecimal fifthGear = new BigDecimal("60000.00");
		BigDecimal sixthGear = new BigDecimal("100000.00");
		BigDecimal rate = ZERO;
		BigDecimal gearPrice = ZERO;
		if (price.compareTo(firstGear) >= 0 && price.compareTo(secondGear) < 0) {
			rate = new BigDecimal("0.05");
			gearPrice = firstGear;

		} else if (price.compareTo(secondGear) >= 0 && price.compareTo(thirdGear) < 0) {
			rate = new BigDecimal("0.1");
			gearPrice = secondGear;
		} else if (price.compareTo(thirdGear) >= 0 && price.compareTo(fourthGear) < 0) {
			rate = new BigDecimal("0.15");
			gearPrice = thirdGear;
		} else if (price.compareTo(fourthGear) >= 0 && price.compareTo(fifthGear) < 0) {
			rate = new BigDecimal("0.2");
			gearPrice = fourthGear;
		} else if (price.compareTo(fifthGear) >= 0 && price.compareTo(sixthGear) < 0) {
			rate = new BigDecimal("0.25");
			gearPrice = fifthGear;
		} else if (price.compareTo(sixthGear) >= 0) {
			rate = new BigDecimal("0.3");
			gearPrice = sixthGear;
		}

		Map<String, BigDecimal> map = new HashMap<>();
		map.put("gearRate", rate);
		map.put("gearPrice", gearPrice);
		return map;
	}*/

    @Override
    public void checkBalanceToBalanceTask() {

        TaskMethod task = TaskMethod.CheckBalanceToBalanceTask;
        Integer interval = task.getCode();
        YgQuartzJob jobMode = YgQuartzJob.Balance;
        ygTaskTimeService.execute(task, interval, new YgTaskTimeTemplate() {

            @Override
            public void execute(Date endDate) throws Exception {

                Date currentDate = new Date();
                Date startDate = DateConvertUtils.addDay(endDate, -interval);
                List<YgOrder> list = ygOrderService.findOrderBySendTime(startDate, endDate);
                if (CollectionUtils.isNotEmpty(list)) {
                    List<String> jobNames = list.stream().map(o -> jobMode.name() + "_" + o.getOrderId()).collect(Collectors.toList());
                    List<ScheduleJob> exitJobs = scheduleJobService.findJobByJobNames(jobNames.toArray(new String[jobNames.size()]));
                    if (CollectionUtils.isNotEmpty(exitJobs)) {
                        List<String> exitNames = exitJobs.stream().map(job -> job.getJobName()).collect(Collectors.toList());
                        jobNames.removeAll(exitNames);
                    }
                    logger.info(jobNames);
                    for (YgOrder o : list) {
                        String jobName = YgQuartzJob.Balance.name() + "_" + o.getOrderId();
                        if (jobNames.contains(jobName)) {

                            Date cronDate = DateConvertUtils.addDay(o.getSendTime(), 15);
                            if (cronDate.before(currentDate)) {
                                cronDate = DateConvertUtils.addMinute(currentDate, 10);
                            }
                            String cron = DateConvertUtils.format(cronDate, DateConvertUtils.DATE_FORMAT_CRON);
                            Map<String, Object> dataMap = new HashMap<>();
                            dataMap.put("orderId", o.getOrderId());
                            ScheduleJob sch = new SchJob(jobName, jobMode.name(), "DWH", 1, cron, "预收入转成长基金", jobMode.getSpringId(), jobMode.getMethodName(),
                                    dataMap);
                            sch.setCreateBy("check");
                            sch.setCreateTime(currentDate);
                            sch.setCronDate(cronDate);

                            Message msg = scheduleJobService.addJobToSchedule(sch);
                            if (msg.getType().equals(Message.Type.success)) {
                                scheduleJobService.save(sch);
                            } else {
                                throw new YgException(msg.getContent());
                            }

                        }
                    }

                }

            }
        });
    }

    @Override
    public void generateInviteCode() {
        Date now = new Date();
        try {
            Date startDate = DateConvertUtils.getMonthStartDate(now); // 本月初
            Date endDate = DateConvertUtils.getDateEnd(DateConvertUtils.getMonthEndDate(now)); // 本月末
            System.out.println(DateConvertUtils.formatDateTime(startDate) + "-->" + DateConvertUtils.formatDateTime(endDate) + "为所有代理用户生成邀请码任务启动。。。。。");
            List<YgUser> userList = ygUserService.findByUserType(UserType.UserAgent); // 当前所有代理用户
            if (CollectionUtils.isEmpty(userList)) {
                logger.warn("当前查询代理用户为空");
            }
            List<Long> userIdList = userList.stream().map(o -> o.getId()).collect(Collectors.toList());
            List<YgAgentInviteRecord> recordList = ygAgentInviteRecordService.findByUserIdListAndBetweenTime(userIdList, startDate, endDate); // 所有代理用户本月已生成的邀请码记录
            List<Long> existsUserIdList = null;
            if (CollectionUtils.isNotEmpty(recordList)) {
                existsUserIdList = recordList.stream().map(o -> o.getUserId()).collect(Collectors.toList());
            }
            List<Long> successList = new ArrayList<>();
            List<Long> errorList = new ArrayList<>();
            for (YgUser user : userList) {
                if (CollectionUtils.isNotEmpty(existsUserIdList) && existsUserIdList.indexOf(user.getId()) != -1) {
                    logger.warn("该用户本月已生成邀请码，userId:" + user.getId());
                    continue;
                }
                try {
                    int row = ygAgentInviteRecordService.generateInviteCodeToUser(user, now);
                    if (row > 0) {
                        successList.add(user.getId());
                    } else {
                        errorList.add(user.getId());
                    }
                } catch (Exception e) {
                    logger.error("本月需要添加邀请码记录数失败，" + ExceptionUtil.getExceptionMsg(e));
                    errorList.add(user.getId());
                }
            }
            logger.info("本月添加邀请码成功的用户集:" + successList.size());
            logger.info("本月添加邀请码失败的用户集:" + errorList.size());
            System.out.println(DateConvertUtils.formatDateTime(startDate) + "-->" + DateConvertUtils.formatDateTime(endDate) + "为所有代理用户生成邀请码任务结束。");
            ygTaskTimeService.saveOrUpdate("GenerateInviteCode", now, "【每月生成邀请码】执行成功");
        } catch (Exception e) {
            ygTaskTimeService.saveOrUpdate("GenerateInviteCode", now, "【每月生成邀请码】执行失败，" + ExceptionUtil.getExceptionMsg(e));
        }
    }

    @Override
    public void notPassCultivationByMonth() {
        Date month = DateConvertUtils.addMonth(new Date(), -1);
        Date start = DateConvertUtils.getMonthStartDate(month);
        Date end = DateConvertUtils.getMonthEndDate(month);
        List<YgUserCultivationDay> list = ygUserCultivationDayService.getSumGroupByUserId(start, end);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        String to = "guohao@yiigoo.com,xueming@yiigoo.com,jiangyunbo@yiigoo.com,sunshuo@yiigoo.cn";
        StringBuffer str = new StringBuffer();
        str.append(
                "<html><head><style>.table-d table{ background:#000;font-size:14px} .table-d table td{ background:#FFF} h5{width: auto;margin-right: 20px} .title{display: flex;line-height: 10px}");
        str.append("</style></head><body>");
        str.append("<div class='table-d'>");
        str.append("<table width='800' border='0' cellspacing='1' cellpadding='0'><tr><td width='20%'>用户名</td>" + "<td width='20%'>月份</td>"
                + "<td width='20%'>耕耘成果</td></tr>");
        for (YgUserCultivationDay day : list) {
            BigDecimal price = day.getTotalPrice();
            if (price.compareTo(new BigDecimal("500.00")) >= 0) { // 达到保级要求：500
                continue;
            }
            YgAgentInviteRecord agentInviteRecord = ygAgentInviteRecordService.findValidByReceiveUserId(day.getUserId());
            if (agentInviteRecord == null || DateConvertUtils.getMonthEndDate(agentInviteRecord.getExpireTime()).after(end)) { // 过滤非代理用户和有效期用户
                continue;
            }
            str.append("<tr><td>" + day.getUserName() + "</td>");
            str.append(" <td>" + DateConvertUtils.getMonth(month) + "</td>");
            str.append(" <td>" + price + "</td>");
        }
        str.append("</table>");
        try {
            mailUtil.sendWithHtml(to.split(","), DateConvertUtils.format(month, "yyyyMM") + "月份 代理未达到保级要求名单", str.toString());
            ygTaskTimeService.saveOrUpdate("notPassCultivationByMonth", new Date(), "【统计每月未达到保级要求的用户】执行成功");
        } catch (Exception e) {
            e.printStackTrace();
            ygTaskTimeService.saveOrUpdate("notPassCultivationByMonth", new Date(), "【统计每月未达到保级要求的用户】执行失败" + ExceptionUtil.getExceptionMsg(e));
        }
    }

    @Override
    public void doCancelGroupOrder(Long orderId, List<String> completeCodeList) {
        List<YgUserBalanceDetail> detailList = preBalanceHandler.doCancelGroupOrder(orderId, completeCodeList);
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        List<YgUserBalanceDetail> resultList = removeExitDetail(detailList, BalanceType.PreIncome);
        if (CollectionUtils.isEmpty(resultList)) {
            return;
        }
        Set<Long> set = resultList.stream().map(YgUserBalanceDetail::getUserId).collect(Collectors.toSet());
        int i = ygUserBalanceService.addBalacneDetailByBatch(resultList);
        if (i > 0) {
            ygUserBalanceService.resetUserBalance(BalanceType.PreIncome, new ArrayList<>(set));
            try {
                sendBalanceMsg(resultList, BalanceType.PreIncome);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
